package com.karolak.math;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.math3.complex.Complex;

public class MathUtils {

	public static double[] abs(double[] input) {
		double[] out = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			out[i] = Math.abs(input[i]);
		}
		return out;
	}

	public static double[][] to2D(double[] input) {
		double[][] ar = new double[2][input.length];
		ar[1] = input;
		for (int i = 0; i < input.length; i++) {
			ar[0][i] = i;
		}
		return ar;
	}

	public static double[][] to2D(double[] x, double[] y) {
		double[][] ar = new double[2][];
		ar[0] = x;
		ar[1] = y;
		return ar;
	}

	public static double[] getX(int size) {
		double[] ar = new double[size];
		for (int i = 0; i < size; i++) {
			ar[i] = i;
		}
		return ar;
	}

	public static double[] filterValues(double[] input, double level) {
		double[] output = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			if (Math.abs(input[i]) == level) {
				output[i] = input[i];
			} else {
				output[i] = 0;
			}
		}
		return output;
	}

	public static float[] toFloat(double[] input) {
		float[] ouptut = new float[input.length];
		for (int i = 0; i < input.length; i++) {
			ouptut[i] = (float) input[i];
		}
		return ouptut;
	}

	public static double[] toReal(Complex[] input) {
		double[] ouptut = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			ouptut[i] = input[i].getReal();
		}
		return ouptut;
	}

	public static double[] toReal(Complex[] input, double multiply) {
		double[] ouptut = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			ouptut[i] = input[i].getReal() * multiply;
		}
		return ouptut;
	}

	public static double[] toImaginary(Complex[] input) {
		double[] ouptut = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			ouptut[i] = input[i].getImaginary();
		}
		return ouptut;
	}

	public static double[] add(double[]... args) {
		if (args == null || args[0] == null) {
			return new double[]{};
		}
		double[] sum = new double[args[0].length];
		for (int x = 0; x < sum.length; x++) {
			for (int i = 0; i < args.length; i++) {
				sum[x] = sum[x] + args[i][x];
			}
		}
		return sum;
	}

	public static double[] add(double[] ar, double value) {
		double[] sum = new double[ar.length];
		for (int i = 0; i < sum.length; i++) {
			sum[i] = ar[i] + value;

		}
		return sum;
	}

	public static Complex[] sortDesc(Complex[] input) {
		Comparator<Complex> c = new Comparator<Complex>() {
			public int compare(Complex arg0, Complex arg1) {
				Double d0 = Double.valueOf(arg0.abs());
				Double d1 = Double.valueOf(arg1.abs());
				return -d0.compareTo(d1);
			}
		};
		Arrays.sort(input, c);
		return input;
	}

	public static double[] toAbs(Complex[] input) {
		double[] ouptut = new double[input.length];
		for (int i = 0; i < input.length; i++) {
			ouptut[i] = input[i].abs();
		}
		return ouptut;
	}

	public static Complex[] filter(Complex[] input, Complex level) {
		Complex[] output = new Complex[input.length];
		for (int i = 0; i < input.length; i++) {
			if (input[i].equals(level)) {
				output[i] = input[i];
			} else {
				output[i] = Complex.ZERO;
			}
		}
		return output;
	}

	public static Complex[] filter(Complex[] input, Complex level, int outputSize) {
		Complex[] output = new Complex[outputSize];
		for (int i = 0; i < outputSize; i++) {
			if (i < input.length && input[i].equals(level)) {
				output[i] = input[i];
				System.out.println("Found match level:" + level + ", i:" + i);
			} else {
				output[i] = Complex.ZERO;
			}
		}
		return output;
	}

	public static double getMax(double[] input) {
		double max = Double.MIN_VALUE;
		for (double d : input) {
			if (d > max) {
				max = d;
			}
		}
		return max;
	}

	public static double getMin(double[] input) {
		double min = Double.MAX_VALUE;
		for (double d : input) {
			if (d < min) {
				min = d;
			}
		}
		return min;
	}

	public static double[] toArray(List<Double> input) {
		double[] output = new double[input.size()];
		for (int i = 0; i < input.size(); i++) {
			output[i] = input.get(i);
		}
		return output;
	}
}
